#!/usr/bin/env python

import os
import wx
import app
import copy
import model
import dialog
import printout
import component
import BeautifulSoup

class Main(component.Presenter):
    '''Main class
    
    @author Julot <andy.julot@gmail.com>
    @since Saturday, January 14, 2012. 09:07 AM'''
    
    _animeId = None
    
    def __init__(self, view, interactor):
        super(Main, self).__init__(view, interactor)
        self._printData = wx.PrintData()
        self._printData.SetPrintMode(wx.PRINT_MODE_PRINTER)
        self._printData.SetQuality(wx.PRINT_QUALITY_HIGH)
        self._printDialogData = wx.PrintDialogData(self._printData)
        self._printer = wx.Printer(self._printDialogData)
        
        self.readSashPos()
        self.populateTitles()
    
    def onClose(self):
        super(Main, self).onClose()
        self.view.anime.image.clear()
        self.writeSashPos()
    
    def close(self):
        self.view.Close()
    
    def readSashPos(self):
        config = app.Config()
        key = '%s/Sash' % self.view.Name
        pos = config.ReadInt(key, -1)
        if pos != -1: self.view.splitter.SashPosition = pos
        key = '%s/AnimeSashV' % self.view.Name
        pos = config.ReadInt(key, -1)
        if pos != -1: self.view.anime.splitterV.SashPosition = pos
        key = '%s/AnimeSashH' % self.view.Name
        pos = config.ReadInt(key, -1)
        if pos != -1: self.view.anime.splitterH.SashPosition = pos
    
    def writeSashPos(self):
        config = app.Config()
        key = '%s/Sash' % self.view.Name
        config.WriteInt(key, self.view.splitter.SashPosition)
        key = '%s/AnimeSashV' % self.view.Name
        config.WriteInt(key, self.view.anime.splitterV.SashPosition)
        key = '%s/AnimeSashH' % self.view.Name
        config.WriteInt(key, self.view.anime.splitterH.SashPosition)
    
    def populateTitles(self, filter=None):
        self.view.busyInfo('Populating titles...')
        query = model.Title.objects.query()
        query.order_by('value')
        if filter:
            # This is using modified autorm, by adding like to operator list.
            if filter.find('%') < 0:
                filter += '%'
                q = model.Title.objects.query().filter(value__like=filter)
                if not q.count(): filter = '%' + filter
            query.filter(value__like=filter)
        else:
            query.filter(type='main', language='x-jat')
        self.view.titles.values = query
        self.view.idle()
    
    _model = None
    
    def loadModel(self, animeId):
        if (not self._model) or (self._model.aid != animeId):
            anidb = model.Anidb(animeId)
            if anidb.hasXml:
                self._model = anidb
            else:
                self._model = None
        return self._model
    
    def show(self, animeId=None):
        if animeId: self._animeId = animeId
        view = self.view
        view.busyInfo('Loading data...')
        view.ToolBar.aniDb.Value = str(animeId)
        view.ToolBar.enableDownloadXml()
        view.MenuBar.aniDb.downloadXml.Enable()
        anidb = self.loadModel(self._animeId)
        if anidb:
            view.anime.value = anidb
            view.MenuBar.file.mold.Enable()
            view.MenuBar.file.printPreview.Enable()
            view.ToolBar.enablePrint()
            view.ToolBar.enableDownloadImage()
            view.MenuBar.aniDb.downloadImage.Enable()
        else:
            view.anime.clear()
            view.MenuBar.file.mold.Enable(False)
            view.MenuBar.file.printPreview.Enable(False)
            view.ToolBar.disablePrint()
            view.ToolBar.disableDownloadImage()
            view.MenuBar.aniDb.downloadImage.Enable(False)
        self.view.idle()
        
    def confirmImportTitles(self):
        wildcard = 'XML files (*.xml)|*.xml'
        defaultFile = "animetitles.xml"
        style = wx.FD_OPEN | wx.FD_FILE_MUST_EXIST
        return self.view.fileDialog(defaultFile=defaultFile, wildcard=wildcard,
                                    style=style)
    
    def importTitles(self, path):
        view = self.view
        
        view.busyInfo('Dropping index...')
        model.Title.dropIndex()
        
        view.busyInfo('Dropping table...')
        model.Title.dropTable()
        
        view.busyInfo('Cleaning database...')
        model.Title.vacuum()
        
        view.busyInfo('Creating table...')
        model.Title.createTable()
        
        view.busyInfo('Parsing XML file, please wait...')
        xml = BeautifulSoup.BeautifulStoneSoup(open(path).read())
        languages = ('ja', 'en', 'x-jat')
        animes = xml.findAll('anime')
        
        view.busyInfo('Calculating total data...')
        maximum = len(animes)
        view.idle()
        
        message = 'Importing data #### of ####...'
        style = (wx.PD_SMOOTH | wx.PD_APP_MODAL | wx.PD_REMAINING_TIME |
                 wx.PD_ELAPSED_TIME | wx.PD_AUTO_HIDE | wx.PD_CAN_ABORT)
        view.progressDialog('Import XML', message, maximum, style)
        count = 0
        for anime in animes:
            count += 1
            animeId = anime.get('aid')
            s = 'Importing data %s of %s...'
            (keepGoing, skip) = view.updateProgress(count, s % (count, maximum))
            for title in anime.findAll('title'):
                language = title.get('xml:lang')
                if language in languages:
                    r = model.Title()
                    r.type = title.get('type')
                    r.language = language
                    r.animeId = animeId
                    r.value = title.contents[0]
                    r.save()
            if not keepGoing:
                s  = 'Are you sure you want to cancel import?'
                style = wx.YES_NO | wx.ICON_WARNING
                result = view.messageDialog(s, 'Import XML', style)
                if result == wx.ID_YES: break
                else: view.resumeProgress()
        view.idle()
        
        view.busyInfo('Creating index...')
        model.Title.createIndex()
        view.idle()
        
    def loadCover(self, animeId):
        anidb = self.loadModel(animeId)
        image = wx.Image(anidb.picturePath, wx.BITMAP_TYPE_ANY)
        description = self.view.anime.description.Value
        if self.view.anime.info.SelectedItemCount:
            index = self.view.anime.info.GetFirstSelected()
            title = self.view.anime.info.GetItemText(index, 1)
            pos = title.rfind(' (')
            if pos: title = title[0:pos]
            kanjiTitle = title
            romanjiTitle = title
        else:
            kanjiTitle = anidb.kanjiTitle
            romanjiTitle = anidb.romanjiTitle
        
        return printout.Cover(kanjiTitle, romanjiTitle, image, anidb.startYear,
                              anidb.startMonth, anidb.startDay, description)
    
    def mold(self):
        po = self.loadCover(self._animeId)
        if not self._printer.Print(self.view, po, False) \
           and self._printer.GetLastError() == wx.PRINTER_ERROR:
            s = "There was a problem printing.\r\n" \
              "Perhaps your current printer is not set correctly?"
            self.view.messageDialog(s, "Printing Error")
        po.Destroy()
    
    def printPreview(self):
        po = self.loadCover(self._animeId)
        po2 = self.loadCover(self._animeId)
        preview = wx.PrintPreview(po, po2, self._printDialogData)
        preview.SetZoom(100)
        if not preview.Ok():
            s = "There was a problem printing.\r\n" \
              "Perhaps your current printer is not set correctly?"
            self.view.messageDialog(s)
        else:
            romanjiTitle = self.loadModel(self._animeId).romanjiTitle
            frame = wx.PreviewFrame(preview, self.view, romanjiTitle)
            frame.Initialize()
            frame.Position = self.view.Position
            frame.Size = self.view.Size
            frame.Show(True)
    
    def confirmDownloadXml(self):
        anidb = model.Anidb(self._animeId)
        if anidb.hasXml:
            s  = 'The data you requested is already available.\r\n'
            s += 'Are you sure you want to redownload?'
            style = wx.YES_NO | wx.ICON_WARNING
            result = self.view.messageDialog(s, 'Download XML', style)
            return True if result == wx.ID_YES else False
        return True
        
    def downloadXml(self):
        self.view.busyInfo('Downloading anime information...')
        anidb = model.Anidb(self._animeId)
        r = anidb.downloadXml()
        self.view.idle()
        if not r: self.view.messageDialog('Failed downloading XML.', 'Error')
        return r
    
    def confirmDownloadImage(self):
        anidb = self.loadModel(self._animeId)
        if anidb.hasPicture:
            s  = 'The image you requested is already available.\r\n'
            s += 'Are you sure you want to redownload?'
            style = wx.YES_NO | wx.ICON_WARNING
            result = self.view.messageDialog(s, 'Download image', style)
            return True if result == wx.ID_YES else False
        return True
        
    def downloadImage(self):
        self.view.busyInfo('Downloading anime image...')
        anidb = self.loadModel(self._animeId)
        r = anidb.downloadImage()
        self.view.idle()
        if r: self.view.messageDialog('Failed downloading image.', 'Error')
        return r

    _about = None
    
    def showAbout(self):
        if not self._about:
            self._about = dialog.About(self.view)
        self._about.Center()
        self._about.Show()
    
    def setupPrinter(self):
        psdd = wx.PageSetupDialogData(self._printData)
        psdd.CalculatePaperSizeFromId()
        dlg = wx.PageSetupDialog(self.view, psdd)
        dlg.ShowModal()
        self._printData = wx.PrintData(dlg.PageSetupData.PrintData)
        dlg.Destroy()
    